package com.github.data_manage.service

import com.github.data_manage.dao.ContrastBusinessDataDao
import com.github.data_manage.dao.ContrastDao
import com.github.data_manage.dao.FundBusinessDataDao
import com.github.data_manage.dao.FundDepthResearchAttachAnnualInfoDao
import com.github.data_manage.dao.FundDepthResearchContrastAttachAnnualInfoDao
import com.github.data_manage.dao.FundDepthResearchAttachDao
import com.github.data_manage.dao.FundDepthResearchAttachQuarterlyInfoDao
import com.github.data_manage.dao.FundDepthResearchContrastAttachQuarterlyInfoDao
import com.github.data_manage.dao.FundDepthResearchContrastAttachDao
import com.github.data_manage.domain.po.CumulativeInfo
import com.github.data_manage.domain.po.ExposureInfo
import com.github.data_manage.domain.po.Fund
import com.github.data_manage.domain.po.FundDepthResearchAttach
import com.github.data_manage.domain.po.FundDepthResearchAttachAnnualInfo
import com.github.data_manage.domain.po.FundDepthResearchAttachQuarterlyInfo
import com.github.data_manage.domain.po.FundDepthResearchContrastAttachAnnualInfo
import com.github.data_manage.domain.po.FundDepthResearchContrastAttachQuarterlyInfo
import com.github.data_manage.domain.po.FundDepthResearchContrastAttach
import com.github.data_manage.util.CollectionExtensions.getNullWhenOutOfIndex
import com.github.data_manage.util.DataUtils
import com.github.data_manage.util.DataUtils.avg
import com.github.data_manage.util.DataUtils.standardDeviation
import com.github.data_manage.util.DataUtils.ytd
import com.github.data_manage.util.DateTimeUtils.Companion.atEndOfMonth
import com.github.data_manage.util.DateTimeUtils.Companion.quarter
import com.github.data_manage.util.consumeAsyncBlocking
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.math.RoundingMode
import java.sql.Types
import java.time.LocalDate
import kotlin.arrayOf
import kotlin.plus

/**
 *
 * @author chenhainan
 * @since 2025/8/12
 */
@Service
class FundDepthResearchAttachService(
    private val fundDepthResearchAttachDao: FundDepthResearchAttachDao,
    private val fundBusinessDataDao: FundBusinessDataDao,
    private val fundDepthResearchContrastAttachDao: FundDepthResearchContrastAttachDao,
    private val contrastBusinessDataDao: ContrastBusinessDataDao,
    private val fundDepthResearchContrastAttachAnnualInfoDao: FundDepthResearchContrastAttachAnnualInfoDao,
    private val fundDepthResearchContrastAttachQuarterlyInfoDao: FundDepthResearchContrastAttachQuarterlyInfoDao,
    private val fundDepthResearchAttachAnnualInfoDao: FundDepthResearchAttachAnnualInfoDao,
    private val fundDepthResearchAttachQuarterlyInfoDao: FundDepthResearchAttachQuarterlyInfoDao,
    private val contrastDao: ContrastDao,
    private val jdbcTemplate: JdbcTemplate
) {


    /**
     * 计算附加信息中的数据
     */
    fun handleAttachInfo(fund: Fund) {
        val fundId = fund.fundId!!
        val fundAllDepthResearchAttachInfos =
            fundDepthResearchAttachDao.findAllByFundIdIs(fundId).sortedBy { it.dataMonth }

        val modifiedAttachInfos = ArrayList<FundDepthResearchAttach>(fundAllDepthResearchAttachInfos.size + 1)

        for ((index, depthResearchAttach) in fundAllDepthResearchAttachInfos.withIndex()) {
//        fundAllDepthResearchAttachInfos.withIndex().foreachAsyncBlocking { (index, depthResearchAttach) ->
            val lastMonthAttach = fundAllDepthResearchAttachInfos.getNullWhenOutOfIndex(index - 1)
            val currentMonth = depthResearchAttach.dataMonth.atEndOfMonth()
            // 当前月的Strategy AUM 减去上个月的Strategy AUM
            depthResearchAttach.changeInStrategyAum =
                if (index == 0) {
                    BigDecimal.ZERO
                } else {
                    (depthResearchAttach.strategyAumMn?.subtract(
                        lastMonthAttach?.strategyAumMn ?: BigDecimal.ZERO
                    ) ?: BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP)
                }
            // 上月Strategy AUM * (1+ 当月 return）
            depthResearchAttach.changeInStrategyAumDueToPerformance =
                if (index == 0) {
                    BigDecimal.ZERO
                } else {
                    (lastMonthAttach?.strategyAumMn?.multiply(
                        fundBusinessDataDao.findFundBusinessDataByFundIdAndTime(
                            fundId,
                            currentMonth
                        )?.value?.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP) ?: BigDecimal.ZERO
                    ) ?: BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP)
                }
            // changeInStrategyAum - changeInStrategyAumDueToPerformance
            depthResearchAttach.changeInStrategyAumDueToInflowAppro =
                if (index == 0) {
                    BigDecimal.ZERO
                } else {
                    (depthResearchAttach.changeInStrategyAum?.subtract(
                        depthResearchAttach.changeInStrategyAumDueToPerformance ?: BigDecimal.ZERO
                    ) ?: BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP)
                }
            // 当月FundAUM - 上月FundAUM
            depthResearchAttach.changeInFundAum =
                if (index == 0) {
                    BigDecimal.ZERO
                } else {
                    (depthResearchAttach.fundAumMn?.subtract(
                        lastMonthAttach?.fundAumMn ?: BigDecimal.ZERO
                    ) ?: BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP)
                }
            // 上月FundAUM * (1+ 当月 return）
            depthResearchAttach.changeInFundAumDueToPerformance =
                if (index == 0) {
                    BigDecimal.ZERO
                } else {
                    (lastMonthAttach?.fundAumMn?.multiply(
                        fundBusinessDataDao.findFundBusinessDataByFundIdAndTime(
                            fundId,
                            currentMonth
                        )?.value?.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP) ?: BigDecimal.ZERO
                    ) ?: BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP)
                }
            // changeInFundAum - changeInFundAumDueToPerformance
            depthResearchAttach.changeInFundAumDueToInflowAppro =
                if (index == 0) {
                    BigDecimal.ZERO
                } else {
                    (depthResearchAttach.changeInFundAum?.subtract(
                        depthResearchAttach.changeInFundAumDueToPerformance ?: BigDecimal.ZERO
                    ) ?: BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP)
                }
            // 包含当月所以所有的月份数量必须减去 1
            // 过去3个月总回报：（1+R1）*(1+R2)*(1+R3)-1，其中R3当月回报
            depthResearchAttach.threeMRollPerf =
                if (index < 2) {
                    BigDecimal.ZERO
                } else {
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(2), currentMonth)
                        .ytd()
                }

            // 过去6个月总回报：（1+R1）*(1+R2)*...*(1+R6)-1，其中R6当月回报
            depthResearchAttach.sixMRollPerf =
                if (index < 5) {
                    BigDecimal.ZERO
                } else {
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(5), currentMonth)
                        .ytd()
                }
            // 过去12个月总回报：（1+R1）*(1+R2)*...*(1+R12)-1，其中R12当月回报
            depthResearchAttach.twelveMRollPerf =
                if (index < 11) {
                    BigDecimal.ZERO
                } else {
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(11), currentMonth)
                        .ytd()
                }
            // 过去36个月总回报：（1+R1）*(1+R2)*...*(1+R36)-1，其中R36当月回报
            depthResearchAttach.thirtySixMRollPerf =
                if (index < 35) {
                    BigDecimal.ZERO
                } else {
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(35), currentMonth)
                        .ytd()
                }
            // 过去12个月（含当月）回报波动率：过往12个月月回报率标准差*（12）^(0.5)
            depthResearchAttach.twelveMRollVol =
                if (index < 11) {
                    BigDecimal.ZERO
                } else {
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(11), currentMonth)
                        .standardDeviation()
                }
            // 过去36个月（含当月）回报波动率：过往12个月月回报率标准差*（12）^(0.5)
            depthResearchAttach.thirtySixMRollVol =
                if (index < 35) {
                    BigDecimal.ZERO
                } else {
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(35), currentMonth)
                        .standardDeviation()
                }
            // 2007年11月-2008年7月 cumulative return：（1+R1）*(1+R2)*...*(1+R9)-1
            depthResearchAttach.subprimeCrisisNov07Jul08 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2007, 11, 30), LocalDate.of(2008, 7, 31))
                    .ytd()
            // 2008.08-2008.10
            depthResearchAttach.creditMeltdownAug08Oct08 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2008, 8, 31), LocalDate.of(2008, 10, 31))
                    .ytd()
            // 2010.05-2010.06
            depthResearchAttach.greeceDebtCrisisMay10Jun10 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2010, 5, 31), LocalDate.of(2010, 6, 30))
                    .ytd()
            // 2011.05-2011.09
            depthResearchAttach.uSEuropeCrisisMay11Sep11 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2011, 5, 31), LocalDate.of(2011, 9, 30))
                    .ytd()
            // 2012.03-2012.05
            depthResearchAttach.euroSovereignDebtCrisisIIMar12May12 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2012, 3, 31), LocalDate.of(2012, 5, 31))
                    .ytd()
            // 2015.05-2015.09
            depthResearchAttach.rMBDevaluationShockMay15Sep15 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2015, 5, 31), LocalDate.of(2015, 9, 30))
                    .ytd()
            // 2016.01-2016.02
            depthResearchAttach.chinaCircuitBreakerShockJan16Feb16 =
                findFundBusinessDataInTimeRange(
                    fundId,
                    LocalDate.of(2016, 1, 31),
                    LocalDate.of(2016, 2, 1).atEndOfMonth()
                ).ytd()
            // 2020.03
            depthResearchAttach.covid19Mar2020 =
                findFundBusinessDataInTimeRange(fundId, LocalDate.of(2020, 3, 1), LocalDate.of(2020, 3, 31))
                    .ytd()

            // Exposure_Long + Exposure_Short
            depthResearchAttach.exposureNet = (depthResearchAttach.exposureLong ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureShort ?: BigDecimal.ZERO)

            // Exposure_Long + Exposure_Short
            depthResearchAttach.exposureGross = (depthResearchAttach.exposureLong ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureShort ?: BigDecimal.ZERO)

            val exposureInfo = ExposureInfo()
            exposureIndustry(exposureInfo, depthResearchAttach)
            exposureMarketValue(exposureInfo, depthResearchAttach)
            exposureArea(exposureInfo, depthResearchAttach)

            depthResearchAttach.exposureInfo = exposureInfo

            // 过往所有Exposure_Net 求平均
            depthResearchAttach.averageNet =
                fundAllDepthResearchAttachInfos.map { it.exposureNet ?: BigDecimal.ZERO }.avg()
            // 过往所有Exposure_Gross 求平均
            depthResearchAttach.averageGross =
                fundAllDepthResearchAttachInfos.map { it.exposureGross ?: BigDecimal.ZERO }.avg()
            // 过往所有Exposure_Long 求平均
            depthResearchAttach.averageLong =
                fundAllDepthResearchAttachInfos.map { it.exposureLong ?: BigDecimal.ZERO }.avg()
            // 过往所有Exposure_Short 求平均
            depthResearchAttach.averageShort =
                fundAllDepthResearchAttachInfos.map { it.exposureShort ?: BigDecimal.ZERO }.avg()

            // Top 1 Long position_Exposure / Exposure_Long
            depthResearchAttach.topOneLongDivideTotal =
                if (depthResearchAttach.exposureLong != null && depthResearchAttach.exposureLong!!.compareTo(BigDecimal.ZERO) != 0) {
                    (depthResearchAttach.top1LongPositionExposure ?: BigDecimal.ZERO).divide(
                        depthResearchAttach.exposureLong,
                        2,
                        RoundingMode.HALF_UP
                    )
                } else {
                    BigDecimal.ZERO
                }
            // Top 5 Long position_Exposure / Exposure_Long
            depthResearchAttach.topFiveLongDivideTotal =
                if (depthResearchAttach.exposureLong != null && depthResearchAttach.exposureLong!!.compareTo(BigDecimal.ZERO) != 0) {
                    (depthResearchAttach.exposureTop5Longs ?: BigDecimal.ZERO).divide(
                        depthResearchAttach.exposureLong,
                        2,
                        RoundingMode.HALF_UP
                    )
                } else {
                    BigDecimal.ZERO
                }
            // Top 10 Long position_Exposure / Exposure_Long
            depthResearchAttach.topTenLongDivideTotal =
                if (depthResearchAttach.exposureLong != null && depthResearchAttach.exposureLong!!.compareTo(BigDecimal.ZERO) != 0) {
                    (depthResearchAttach.exposureTop10Longs ?: BigDecimal.ZERO).divide(
                        depthResearchAttach.exposureLong,
                        2,
                        RoundingMode.HALF_UP
                    )
                } else {
                    BigDecimal.ZERO
                }

            // Top 1 Short position_Exposure / Exposure_Short
            depthResearchAttach.topOneShortDivideTotal =
                if (depthResearchAttach.exposureShort != null && depthResearchAttach.exposureShort!!.compareTo(
                        BigDecimal.ZERO
                    ) != 0
                ) {
                    (depthResearchAttach.top1ShortPositionExposure ?: BigDecimal.ZERO).divide(
                        depthResearchAttach.exposureLong,
                        2,
                        RoundingMode.HALF_UP
                    )
                } else {
                    BigDecimal.ZERO
                }

            // Top 5 Short position_Exposure / Exposure_Short
            depthResearchAttach.topFiveShortDivideTotal =
                if (depthResearchAttach.exposureShort != null && depthResearchAttach.exposureShort!!.compareTo(
                        BigDecimal.ZERO
                    ) != 0
                ) {
                    (depthResearchAttach.exposureTop5Shorts ?: BigDecimal.ZERO).divide(
                        depthResearchAttach.exposureLong,
                        2,
                        RoundingMode.HALF_UP
                    )
                } else {
                    BigDecimal.ZERO
                }

            // Top 10 Short position_Exposure / Exposure_Short
            depthResearchAttach.topTenShortDivideTotal =
                if (depthResearchAttach.exposureShort != null && depthResearchAttach.exposureShort!!.compareTo(
                        BigDecimal.ZERO
                    ) != 0
                ) {
                    (depthResearchAttach.exposureTop10Shorts ?: BigDecimal.ZERO).divide(
                        depthResearchAttach.exposureLong,
                        2,
                        RoundingMode.HALF_UP
                    )
                } else {
                    BigDecimal.ZERO
                }

            // 类似基金return NAV，默认最早数据前一个月数值为100，之后每个月数据为前一个月值*（1+当月Beta Cumulative），举例：第一个月为100*（1+Beta [1]）；第二个月为 第一个月的值*（1+Beta [2]);

            depthResearchAttach.longCumulative =
                cumulativeCalc(lastMonthAttach?.longCumulative, depthResearchAttach.performanceLong)
//                (lastMonthAttach?.longCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceLong
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )

            depthResearchAttach.shortCumulative =
                cumulativeCalc(lastMonthAttach?.shortCumulative, depthResearchAttach.performanceShort)
//                (lastMonthAttach?.shortCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceShort
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )

            cumulativeInfo(depthResearchAttach, lastMonthAttach)

            modifiedAttachInfos.add(depthResearchAttach)
        }

        fundDepthResearchAttachDao.saveAll(modifiedAttachInfos)
        handleQuarterlyInfo(fund)
        handleAnnuallyInfo(fund)
    }


    /**
     * 行业的 exposure 信息
     */
    private fun exposureIndustry(exposureInfo: ExposureInfo, depthResearchAttach: FundDepthResearchAttach) {
        // exposureConsumerStaplesS + exposureConsumerStaplesL
        exposureInfo.exposureConsumerStaplesNet =
            (depthResearchAttach.exposureConsumerStaplesS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureConsumerStaplesL ?: BigDecimal.ZERO)
        // exposureConsumerDiscretionaryS + exposureConsumerDiscretionaryL
        exposureInfo.exposureConsumerDiscretionaryNet =
            (depthResearchAttach.exposureConsumerDiscretionaryS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureConsumerDiscretionaryL ?: BigDecimal.ZERO)
        // exposureInformationTechnologyS + exposureInformationTechnologyL
        exposureInfo.exposureInformationTechnologyNet =
            (depthResearchAttach.exposureInformationTechnologyS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureInformationTechnologyL ?: BigDecimal.ZERO)
        // exposureFinancialsS + exposureFinancialsL
        exposureInfo.exposureFinancialsNet = (depthResearchAttach.exposureFinancialsS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureFinancialsL ?: BigDecimal.ZERO)
        // exposureHealthCareS + exposureHealthCareL
        exposureInfo.exposureHealthCareNet = (depthResearchAttach.exposureHealthCareS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureHealthCareL ?: BigDecimal.ZERO)
        // exposureIndustrialsS + exposureIndustrialsL
        exposureInfo.exposureIndustrialsNet = (depthResearchAttach.exposureIndustrialsS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureIndustrialsL ?: BigDecimal.ZERO)
        // exposureUtilitiesS + exposureUtilitiesL
        exposureInfo.exposureUtilitiesNet = (depthResearchAttach.exposureUtilitiesS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureUtilitiesL ?: BigDecimal.ZERO)
        // exposureMaterialsS + exposureMaterialsL
        exposureInfo.exposureMaterialsNet = (depthResearchAttach.exposureMaterialsS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureMaterialsL ?: BigDecimal.ZERO)
        // exposureRealEstateS + exposureRealEstateL
        exposureInfo.exposureRealEstateNet = (depthResearchAttach.exposureRealEstateS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureRealEstateL ?: BigDecimal.ZERO)
        // exposureEnergyS + exposureEnergyL
        exposureInfo.exposureEnergyNet = (depthResearchAttach.exposureEnergyS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureEnergyL ?: BigDecimal.ZERO)
        // exposureCommunicationServiceS + exposureCommunicationServiceL
        exposureInfo.exposureCommunicationServiceNet =
            (depthResearchAttach.exposureCommunicationServiceS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureCommunicationServiceL ?: BigDecimal.ZERO)
        // exposureIndexETFS + exposureIndexETFL
        exposureInfo.exposureIndexETFNet = (depthResearchAttach.exposureIndexETFS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureIndexETFL ?: BigDecimal.ZERO)
        // exposureCashS + exposureCashL
        exposureInfo.exposureCashNet = (depthResearchAttach.exposureCashS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureCashL ?: BigDecimal.ZERO)
        // exposureOthersS + exposureOthersL
        exposureInfo.exposureOthersNet = (depthResearchAttach.exposureOthersS ?: BigDecimal.ZERO)
            .add(depthResearchAttach.exposureOthersL ?: BigDecimal.ZERO)


        // exposureConsumerStaplesL - exposureConsumerStaplesL
        exposureInfo.exposureConsumerStaplesGross =
            (depthResearchAttach.exposureConsumerStaplesL ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureConsumerStaplesS ?: BigDecimal.ZERO)
        // exposureConsumerDiscretionaryL - exposureConsumerDiscretionaryL
        exposureInfo.exposureConsumerDiscretionaryGross =
            (depthResearchAttach.exposureConsumerDiscretionaryL ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureConsumerDiscretionaryS ?: BigDecimal.ZERO)
        // exposureInformationTechnologyL - exposureInformationTechnologyL
        exposureInfo.exposureInformationTechnologyGross =
            (depthResearchAttach.exposureInformationTechnologyL ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureInformationTechnologyS ?: BigDecimal.ZERO)
        // exposureFinancialsL - exposureFinancialsL
        exposureInfo.exposureFinancialsGross = (depthResearchAttach.exposureFinancialsL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureFinancialsS ?: BigDecimal.ZERO)
        // exposureHealthCareL - exposureHealthCareL
        exposureInfo.exposureHealthCareGross = (depthResearchAttach.exposureHealthCareL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureHealthCareS ?: BigDecimal.ZERO)
        // exposureIndustrialsL - exposureIndustrialsS
        exposureInfo.exposureIndustrialsGross = (depthResearchAttach.exposureIndustrialsL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureIndustrialsS ?: BigDecimal.ZERO)
        // exposureUtilitiesL - exposureUtilitiesS
        exposureInfo.exposureUtilitiesGross = (depthResearchAttach.exposureUtilitiesL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureUtilitiesS ?: BigDecimal.ZERO)
        // exposureMaterialsL - exposureMaterialsS
        exposureInfo.exposureMaterialsGross = (depthResearchAttach.exposureMaterialsL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureMaterialsS ?: BigDecimal.ZERO)
        // exposureRealEstateL - exposureRealEstateS
        exposureInfo.exposureRealEstateGross = (depthResearchAttach.exposureRealEstateL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureRealEstateS ?: BigDecimal.ZERO)
        // exposureEnergyL - exposureEnergyS
        exposureInfo.exposureEnergyGross = (depthResearchAttach.exposureEnergyL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureEnergyS ?: BigDecimal.ZERO)
        // exposureCommunicationServiceL - exposureCommunicationServiceS
        exposureInfo.exposureCommunicationServiceGross =
            (depthResearchAttach.exposureCommunicationServiceL ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureCommunicationServiceS ?: BigDecimal.ZERO)
        // exposureIndexETFL - exposureIndexETFS
        exposureInfo.exposureIndexETFGross = (depthResearchAttach.exposureIndexETFL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureIndexETFS ?: BigDecimal.ZERO)
        // exposureCashL - exposureCashS
        exposureInfo.exposureCashGross = (depthResearchAttach.exposureCashL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureCashS ?: BigDecimal.ZERO)
        // exposureOthersL - exposureOthersS
        exposureInfo.exposureOthersGross = (depthResearchAttach.exposureOthersL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureOthersS ?: BigDecimal.ZERO)
    }

    /**
     * 市值的 exposure 信息
     */
    private fun exposureMarketValue(exposureInfo: ExposureInfo, depthResearchAttach: FundDepthResearchAttach) {
        // exposureBigger10bnS + exposureBigger10bnL
        exposureInfo.exposureBigger10bnNet =
            (depthResearchAttach.exposureBigger10bnS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureBigger10bnL ?: BigDecimal.ZERO)

        // exposure5To10bnS + exposure5To10bnL
        exposureInfo.exposure5To10bnNet =
            (depthResearchAttach.exposure5To10bnS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposure5To10bnL ?: BigDecimal.ZERO)

        // exposure1To5bnS + exposure1To5bnL
        exposureInfo.exposure1To5bnNet =
            (depthResearchAttach.exposure1To5bnS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposure1To5bnL ?: BigDecimal.ZERO)

        exposureInfo.exposureZeroPointThreeToOnebnNet =
            (depthResearchAttach.exposureZeroPointThreeToOnebnS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureZeroPointThreeToOnebnL ?: BigDecimal.ZERO)

        exposureInfo.exposureLitterZeroPointThreebnNet =
            (depthResearchAttach.exposureLitterZeroPointThreebnS ?: BigDecimal.ZERO)
                .add(depthResearchAttach.exposureLitterZeroPointThreebnS ?: BigDecimal.ZERO)

        // exposureBigger10bnS - exposureBigger10bnL
        exposureInfo.exposureBigger10bnGross = (depthResearchAttach.exposureBigger10bnL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposureBigger10bnS ?: BigDecimal.ZERO)

        // exposure5To10bnS - exposure5To10bnL
        exposureInfo.exposure5To10bnGross = (depthResearchAttach.exposure5To10bnL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposure5To10bnS ?: BigDecimal.ZERO)

        // exposure1To5bnS - exposure1To510bnL
        exposureInfo.exposure1To5bnGross = (depthResearchAttach.exposure1To5bnL ?: BigDecimal.ZERO)
            .subtract(depthResearchAttach.exposure1To5bnS ?: BigDecimal.ZERO)

        exposureInfo.exposureZeroPointThreeToOnebnGross =
            (depthResearchAttach.exposureZeroPointThreeToOnebnL ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureZeroPointThreeToOnebnS ?: BigDecimal.ZERO)
        exposureInfo.exposureLitterZeroPointThreebnGross =
            (depthResearchAttach.exposureLitterZeroPointThreebnL ?: BigDecimal.ZERO)
                .subtract(depthResearchAttach.exposureLitterZeroPointThreebnS ?: BigDecimal.ZERO)
    }

    /**
     * 地区的 exposure 信息
     */
    private fun exposureArea(exposureInfo: ExposureInfo, depthResearchAttach: FundDepthResearchAttach) {
        exposureInfo.exposureUSNet = (depthResearchAttach.exposureUSL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureUSS ?: BigDecimal.ZERO))
        exposureInfo.exposureCanadaNet = (depthResearchAttach.exposureCanadaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureCanadaS ?: BigDecimal.ZERO))
        exposureInfo.exposureBrazilNet = (depthResearchAttach.exposureBrazilL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureBrazilS ?: BigDecimal.ZERO))
        exposureInfo.exposureMexicoNet = (depthResearchAttach.exposureMexicoL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureMexicoS ?: BigDecimal.ZERO))
        exposureInfo.exposureArgentinaNet = (depthResearchAttach.exposureArgentinaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureArgentinaS ?: BigDecimal.ZERO))
        exposureInfo.exposureChileNet = (depthResearchAttach.exposureChileL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureChileS ?: BigDecimal.ZERO))
        exposureInfo.exposureColombiaNet = (depthResearchAttach.exposureColombiaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureColombiaS ?: BigDecimal.ZERO))
        exposureInfo.exposurePeruNet = (depthResearchAttach.exposurePeruL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposurePeruS ?: BigDecimal.ZERO))
        exposureInfo.exposureUKNet = (depthResearchAttach.exposureUKL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureUKS ?: BigDecimal.ZERO))
        exposureInfo.exposureGermanyNet = (depthResearchAttach.exposureGermanyL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureGermanyS ?: BigDecimal.ZERO))
        exposureInfo.exposureFranceNet = (depthResearchAttach.exposureFranceL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureFranceS ?: BigDecimal.ZERO))
        exposureInfo.exposureSwitzerlandNet = (depthResearchAttach.exposureSwitzerlandL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSwitzerlandS ?: BigDecimal.ZERO))
        exposureInfo.exposureNetherlandsNet = (depthResearchAttach.exposureNetherlandsL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureNetherlandsS ?: BigDecimal.ZERO))
        exposureInfo.exposureItalyNet = (depthResearchAttach.exposureItalyL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureItalyS ?: BigDecimal.ZERO))
        exposureInfo.exposureSpainNet = (depthResearchAttach.exposureSpainL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSpainS ?: BigDecimal.ZERO))
        exposureInfo.exposureSwedenNet = (depthResearchAttach.exposureSwedenL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSwedenS ?: BigDecimal.ZERO))
        exposureInfo.exposureSaudiArabiaNet = (depthResearchAttach.exposureSaudiArabiaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSaudiArabiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureUnitedArabEmiratesNet =
            (depthResearchAttach.exposureUnitedArabEmiratesL ?: BigDecimal.ZERO)
                .add((depthResearchAttach.exposureUnitedArabEmiratesS ?: BigDecimal.ZERO))
        exposureInfo.exposureSouthAfricaNet = (depthResearchAttach.exposureSouthAfricaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSouthAfricaS ?: BigDecimal.ZERO))
        exposureInfo.exposureNigeriaNet = (depthResearchAttach.exposureNigeriaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureNigeriaS ?: BigDecimal.ZERO))
        exposureInfo.exposureEgyptNet = (depthResearchAttach.exposureEgyptL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureEgyptS ?: BigDecimal.ZERO))
        exposureInfo.exposureJapanNet = (depthResearchAttach.exposureJapanL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureJapanS ?: BigDecimal.ZERO))
        exposureInfo.exposureChinaNet = (depthResearchAttach.exposureChinaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureChinaS ?: BigDecimal.ZERO))
        exposureInfo.exposureHongKongNet = (depthResearchAttach.exposureHongKongL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureHongKongS ?: BigDecimal.ZERO))
        exposureInfo.exposureTaiwanNet = (depthResearchAttach.exposureTaiwanL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureTaiwanS ?: BigDecimal.ZERO))
        exposureInfo.exposureAustraliaNet = (depthResearchAttach.exposureAustraliaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureAustraliaS ?: BigDecimal.ZERO))
        exposureInfo.exposureIndiaNet = (depthResearchAttach.exposureIndiaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureIndiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureSouthKoreaNet = (depthResearchAttach.exposureSouthKoreaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSouthKoreaS ?: BigDecimal.ZERO))
        exposureInfo.exposureSingaporeNet = (depthResearchAttach.exposureSingaporeL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureSingaporeS ?: BigDecimal.ZERO))
        exposureInfo.exposureIndonesiaNet = (depthResearchAttach.exposureIndonesiaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureIndonesiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureMalaysiaNet = (depthResearchAttach.exposureMalaysiaL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureMalaysiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureThailandNet = (depthResearchAttach.exposureThailandL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureThailandS ?: BigDecimal.ZERO))
        exposureInfo.exposurePhilippinesNet = (depthResearchAttach.exposurePhilippinesL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposurePhilippinesS ?: BigDecimal.ZERO))
        exposureInfo.exposureVietnamNet = (depthResearchAttach.exposureVietnamL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureVietnamS ?: BigDecimal.ZERO))
        exposureInfo.exposureNewZealandNet = (depthResearchAttach.exposureNewZealandL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureNewZealandS ?: BigDecimal.ZERO))
        exposureInfo.exposureOtherCountryNet = (depthResearchAttach.exposureOthersCountryL ?: BigDecimal.ZERO)
            .add((depthResearchAttach.exposureOthersCountryS ?: BigDecimal.ZERO))

        exposureInfo.exposureUSGross = (depthResearchAttach.exposureUSL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureUSS ?: BigDecimal.ZERO))
        exposureInfo.exposureCanadaGross = (depthResearchAttach.exposureCanadaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureCanadaS ?: BigDecimal.ZERO))
        exposureInfo.exposureBrazilGross = (depthResearchAttach.exposureBrazilL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureBrazilS ?: BigDecimal.ZERO))
        exposureInfo.exposureMexicoGross = (depthResearchAttach.exposureMexicoL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureMexicoS ?: BigDecimal.ZERO))
        exposureInfo.exposureArgentinaGross = (depthResearchAttach.exposureArgentinaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureArgentinaS ?: BigDecimal.ZERO))
        exposureInfo.exposureChileGross = (depthResearchAttach.exposureChileL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureChileS ?: BigDecimal.ZERO))
        exposureInfo.exposureColombiaGross = (depthResearchAttach.exposureColombiaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureColombiaS ?: BigDecimal.ZERO))
        exposureInfo.exposurePeruGross = (depthResearchAttach.exposurePeruL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposurePeruS ?: BigDecimal.ZERO))
        exposureInfo.exposureUKGross = (depthResearchAttach.exposureUKL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureUKS ?: BigDecimal.ZERO))
        exposureInfo.exposureGermanyGross = (depthResearchAttach.exposureGermanyL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureGermanyS ?: BigDecimal.ZERO))
        exposureInfo.exposureFranceGross = (depthResearchAttach.exposureFranceL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureFranceS ?: BigDecimal.ZERO))
        exposureInfo.exposureSwitzerlandGross = (depthResearchAttach.exposureSwitzerlandL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSwitzerlandS ?: BigDecimal.ZERO))
        exposureInfo.exposureNetherlandsGross = (depthResearchAttach.exposureNetherlandsL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureNetherlandsS ?: BigDecimal.ZERO))
        exposureInfo.exposureItalyGross = (depthResearchAttach.exposureItalyL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureItalyS ?: BigDecimal.ZERO))
        exposureInfo.exposureSpainGross = (depthResearchAttach.exposureSpainL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSpainS ?: BigDecimal.ZERO))
        exposureInfo.exposureSwedenGross = (depthResearchAttach.exposureSwedenL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSwedenS ?: BigDecimal.ZERO))
        exposureInfo.exposureSaudiArabiaGross = (depthResearchAttach.exposureSaudiArabiaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSaudiArabiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureUnitedArabEmiratesGross =
            (depthResearchAttach.exposureUnitedArabEmiratesL ?: BigDecimal.ZERO)
                .subtract((depthResearchAttach.exposureUnitedArabEmiratesS ?: BigDecimal.ZERO))
        exposureInfo.exposureSouthAfricaGross = (depthResearchAttach.exposureSouthAfricaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSouthAfricaS ?: BigDecimal.ZERO))
        exposureInfo.exposureNigeriaGross = (depthResearchAttach.exposureNigeriaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureNigeriaS ?: BigDecimal.ZERO))
        exposureInfo.exposureEgyptGross = (depthResearchAttach.exposureEgyptL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureEgyptS ?: BigDecimal.ZERO))
        exposureInfo.exposureJapanGross = (depthResearchAttach.exposureJapanL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureJapanS ?: BigDecimal.ZERO))
        exposureInfo.exposureChinaGross = (depthResearchAttach.exposureChinaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureChinaS ?: BigDecimal.ZERO))
        exposureInfo.exposureHongKongGross = (depthResearchAttach.exposureHongKongL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureHongKongS ?: BigDecimal.ZERO))
        exposureInfo.exposureTaiwanGross = (depthResearchAttach.exposureTaiwanL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureTaiwanS ?: BigDecimal.ZERO))
        exposureInfo.exposureAustraliaGross = (depthResearchAttach.exposureAustraliaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureAustraliaS ?: BigDecimal.ZERO))
        exposureInfo.exposureIndiaGross = (depthResearchAttach.exposureIndiaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureIndiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureSouthKoreaGross = (depthResearchAttach.exposureSouthKoreaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSouthKoreaS ?: BigDecimal.ZERO))
        exposureInfo.exposureSingaporeGross = (depthResearchAttach.exposureSingaporeL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureSingaporeS ?: BigDecimal.ZERO))
        exposureInfo.exposureIndonesiaGross = (depthResearchAttach.exposureIndonesiaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureIndonesiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureMalaysiaGross = (depthResearchAttach.exposureMalaysiaL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureMalaysiaS ?: BigDecimal.ZERO))
        exposureInfo.exposureThailandGross = (depthResearchAttach.exposureThailandL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureThailandS ?: BigDecimal.ZERO))
        exposureInfo.exposurePhilippinesGross = (depthResearchAttach.exposurePhilippinesL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposurePhilippinesS ?: BigDecimal.ZERO))
        exposureInfo.exposureVietnamGross = (depthResearchAttach.exposureVietnamL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureVietnamS ?: BigDecimal.ZERO))
        exposureInfo.exposureNewZealandGross = (depthResearchAttach.exposureNewZealandL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureNewZealandS ?: BigDecimal.ZERO))
        exposureInfo.exposureOtherCountryGross = (depthResearchAttach.exposureOthersCountryL ?: BigDecimal.ZERO)
            .subtract((depthResearchAttach.exposureOthersCountryS ?: BigDecimal.ZERO))

    }


    private fun cumulativeInfo(
        depthResearchAttach: FundDepthResearchAttach,
        lastDepthResearchAttach: FundDepthResearchAttach?
    ) {
        val cumulativeInfo: CumulativeInfo = depthResearchAttach.cumulativeInfo ?: CumulativeInfo()
        cumulativeInfo.uSCumulative =
            cumulativeCalc(lastDepthResearchAttach?.cumulativeInfo?.uSCumulative, depthResearchAttach.performanceUS)
//            (lastDepthResearchAttach?.cumulativeInfo?.uSCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceUS
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
        cumulativeInfo.canadaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.canadaCumulative,
                depthResearchAttach.performanceCanada
            )
//            (lastDepthResearchAttach?.cumulativeInfo?.canadaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceCanada
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
        cumulativeInfo.brazilCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.brazilCumulative,
                depthResearchAttach.performanceBrazil
            )
//            (lastDepthResearchAttach?.cumulativeInfo?.brazilCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceBrazil
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
        cumulativeInfo.mexicoCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.mexicoCumulative,
                depthResearchAttach.performanceMexico
            )

//            (lastDepthResearchAttach?.cumulativeInfo?.mexicoCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceMexico
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
        cumulativeInfo.argentinaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.argentinaCumulative,
                depthResearchAttach.performanceArgentina
            )

//            (lastDepthResearchAttach?.cumulativeInfo?.argentinaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceArgentina
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
        cumulativeInfo.chileCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.chileCumulative,
                depthResearchAttach.performanceChile
            )

//            (lastDepthResearchAttach?.cumulativeInfo?.chileCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceChile
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
        cumulativeInfo.colombiaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.colombiaCumulative,
                depthResearchAttach.performanceColombia
            )
//            (lastDepthResearchAttach?.cumulativeInfo?.colombiaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceColombia
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.peruCumulative = (lastDepthResearchAttach?.cumulativeInfo?.peruCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performancePeru
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.uKCumulative = (lastDepthResearchAttach?.cumulativeInfo?.uKCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceUK
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.germanyCumulative = (lastDepthResearchAttach?.cumulativeInfo?.germanyCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceGermany
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.franceCumulative = (lastDepthResearchAttach?.cumulativeInfo?.franceCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceFrance
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.switzerlandCumulative = (lastDepthResearchAttach?.cumulativeInfo?.switzerlandCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSwitzerland
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//
//        cumulativeInfo.netherlandsCumulative = (lastDepthResearchAttach?.cumulativeInfo?.netherlandsCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceNetherlands
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.italyCumulative = (lastDepthResearchAttach?.cumulativeInfo?.italyCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceItaly
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.spainCumulative = (lastDepthResearchAttach?.cumulativeInfo?.spainCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSpain
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.swedenCumulative = (lastDepthResearchAttach?.cumulativeInfo?.swedenCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSweden
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.saudiArabiaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.saudiArabiaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSaudiArabia
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.unitedArabEmiratesCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.unitedArabEmiratesCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceUnitedArabEmirates
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.southAfricaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.southAfricaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSouthAfrica
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.nigeriaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.nigeriaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceNigeria
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.egyptCumulative = (lastDepthResearchAttach?.cumulativeInfo?.egyptCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceEgypt
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.japanCumulative = (lastDepthResearchAttach?.cumulativeInfo?.japanCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceJapan
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.chinaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.chinaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceChina
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.hongKongCumulative = (lastDepthResearchAttach?.cumulativeInfo?.hongKongCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceHongKong
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.taiwanCumulative = (lastDepthResearchAttach?.cumulativeInfo?.taiwanCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceTaiwan
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.australiaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.australiaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceAustralia
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.indiaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.indiaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceIndia
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.southKoreaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.southKoreaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSouthKorea
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.singaporeCumulative = (lastDepthResearchAttach?.cumulativeInfo?.singaporeCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSingapore
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.indonesiaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.indonesiaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceIndonesia
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.malaysiaCumulative = (lastDepthResearchAttach?.cumulativeInfo?.malaysiaCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceMalaysia
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.thailandCumulative = (lastDepthResearchAttach?.cumulativeInfo?.thailandCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceThailand
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//
//        cumulativeInfo.philippinesCumulative = (lastDepthResearchAttach?.cumulativeInfo?.philippinesCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performancePhilippines
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.vietnamCumulative = (lastDepthResearchAttach?.cumulativeInfo?.vietnamCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceVietnam
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.newZealandCumulative = (lastDepthResearchAttach?.cumulativeInfo?.newZealandCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceNewZealand
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//
//        cumulativeInfo.otherCountryCumulative = (lastDepthResearchAttach?.cumulativeInfo?.otherCountryCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceOtherCountry
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//
//        cumulativeInfo.consumerStaplesCumulative = (lastDepthResearchAttach?.cumulativeInfo?.consumerStaplesCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceConsumerStaples
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.consumerDiscretionaryCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.consumerDiscretionaryCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceConsumerDiscretionary
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.informationTechnologyCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.informationTechnologyCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceInformationTechnology
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.financialsCumulative = (lastDepthResearchAttach?.cumulativeInfo?.financialsCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceFinancials
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.healthCareCumulative = (lastDepthResearchAttach?.cumulativeInfo?.healthCareCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceHealthCare
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.industrialsCumulative = (lastDepthResearchAttach?.cumulativeInfo?.industrialsCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceIndustrials
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.utilitiesCumulative = (lastDepthResearchAttach?.cumulativeInfo?.utilitiesCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceUtilities
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.materialsCumulative = (lastDepthResearchAttach?.cumulativeInfo?.materialsCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceMaterials
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.realEstateCumulative = (lastDepthResearchAttach?.cumulativeInfo?.realEstateCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceRealEstate
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.energyCumulative = (lastDepthResearchAttach?.cumulativeInfo?.energyCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceEnergy
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.communicationServiceCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.communicationServiceCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceCommunicationSevices
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.indexETFCumulative = (lastDepthResearchAttach?.cumulativeInfo?.indexETFCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceIndexETF
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.cashCumulative = (lastDepthResearchAttach?.cumulativeInfo?.cashCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceCash
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.othersCumulative = (lastDepthResearchAttach?.cumulativeInfo?.othersCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceOthers
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//
//        cumulativeInfo.bigger10bnCumulative = (lastDepthResearchAttach?.cumulativeInfo?.bigger10bnCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceBigger10bn
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.fiveTo10bnCumulative = (lastDepthResearchAttach?.cumulativeInfo?.fiveTo10bnCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performance5To10bn
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.oneTo5bnCumulative = (lastDepthResearchAttach?.cumulativeInfo?.oneTo5bnCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performance1To5bn
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.zeroPointThreeToOnebnCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.zeroPointThreeToOnebnCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceZeroPointThreeToOnebn
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.litterZeroPointThreebnCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.litterZeroPointThreebnCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceLitterZeroPointThreebn
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//
//        cumulativeInfo.equitiesCumulative = (lastDepthResearchAttach?.cumulativeInfo?.equitiesCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceEquities
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.fixedIncomeCumulative = (lastDepthResearchAttach?.cumulativeInfo?.fixedIncomeCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceFixedIncome
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.currenciesFXCumulative = (lastDepthResearchAttach?.cumulativeInfo?.currenciesFXCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceCurrenciesFX
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//        cumulativeInfo.commoditiesCumulative = (lastDepthResearchAttach?.cumulativeInfo?.commoditiesCumulative
//            ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceCommodities
//            ?: BigDecimal.ZERO)).setScale(
//            2,
//            RoundingMode.HALF_UP
//        )
//
//        cumulativeInfo.alternativeInvestmentsCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.alternativeInvestmentsCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceAlternativeInvestments
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.realEstateAssetClassCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.realEstateAssetClassCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceRealEstateAssetClass
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.otherAssetClassCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.otherAssetClassCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceOthersAssetClass
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.cashSpotCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.cashSpotCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceCashSpot
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.futuresCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.futuresCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceFutures
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.optionsCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.optionsCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceOptions
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.swapsCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.swapsCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceSwaps
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.etfETPCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.etfETPCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceETFsETPs
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
//        cumulativeInfo.otherToolCumulative =
//            (lastDepthResearchAttach?.cumulativeInfo?.otherToolCumulative
//                ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (depthResearchAttach.performanceOthersTool
//                ?: BigDecimal.ZERO)).setScale(
//                2,
//                RoundingMode.HALF_UP
//            )
        cumulativeInfo.uKCumulative =
            cumulativeCalc(lastDepthResearchAttach?.cumulativeInfo?.uKCumulative, depthResearchAttach.performanceUK)
        cumulativeInfo.germanyCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.germanyCumulative,
                depthResearchAttach.performanceGermany
            )
        cumulativeInfo.franceCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.franceCumulative,
                depthResearchAttach.performanceFrance
            )
        cumulativeInfo.switzerlandCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.switzerlandCumulative,
                depthResearchAttach.performanceSwitzerland
            )
        cumulativeInfo.netherlandsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.netherlandsCumulative,
                depthResearchAttach.performanceNetherlands
            )
        cumulativeInfo.italyCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.italyCumulative,
                depthResearchAttach.performanceItaly
            )
        cumulativeInfo.spainCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.spainCumulative,
                depthResearchAttach.performanceSpain
            )
        cumulativeInfo.swedenCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.swedenCumulative,
                depthResearchAttach.performanceSweden
            )
        cumulativeInfo.saudiArabiaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.saudiArabiaCumulative,
                depthResearchAttach.performanceSaudiArabia
            )
        cumulativeInfo.unitedArabEmiratesCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.unitedArabEmiratesCumulative,
                depthResearchAttach.performanceUnitedArabEmirates
            )
        cumulativeInfo.southAfricaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.southAfricaCumulative,
                depthResearchAttach.performanceSouthAfrica
            )
        cumulativeInfo.nigeriaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.nigeriaCumulative,
                depthResearchAttach.performanceNigeria
            )
        cumulativeInfo.egyptCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.egyptCumulative,
                depthResearchAttach.performanceEgypt
            )
        cumulativeInfo.japanCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.japanCumulative,
                depthResearchAttach.performanceJapan
            )
        cumulativeInfo.chinaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.chinaCumulative,
                depthResearchAttach.performanceChina
            )
        cumulativeInfo.hongKongCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.hongKongCumulative,
                depthResearchAttach.performanceHongKong
            )
        cumulativeInfo.taiwanCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.taiwanCumulative,
                depthResearchAttach.performanceTaiwan
            )
        cumulativeInfo.australiaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.australiaCumulative,
                depthResearchAttach.performanceAustralia
            )
        cumulativeInfo.indiaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.indiaCumulative,
                depthResearchAttach.performanceIndia
            )
        cumulativeInfo.southKoreaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.southKoreaCumulative,
                depthResearchAttach.performanceSouthKorea
            )
        cumulativeInfo.singaporeCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.singaporeCumulative,
                depthResearchAttach.performanceSingapore
            )
        cumulativeInfo.indonesiaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.indonesiaCumulative,
                depthResearchAttach.performanceIndonesia
            )
        cumulativeInfo.malaysiaCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.malaysiaCumulative,
                depthResearchAttach.performanceMalaysia
            )
        cumulativeInfo.thailandCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.thailandCumulative,
                depthResearchAttach.performanceThailand
            )
        cumulativeInfo.philippinesCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.philippinesCumulative,
                depthResearchAttach.performancePhilippines
            )
        cumulativeInfo.vietnamCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.vietnamCumulative,
                depthResearchAttach.performanceVietnam
            )
        cumulativeInfo.newZealandCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.newZealandCumulative,
                depthResearchAttach.performanceNewZealand
            )
        cumulativeInfo.otherCountryCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.otherCountryCumulative,
                depthResearchAttach.performanceOtherCountry
            )
        cumulativeInfo.consumerStaplesCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.consumerStaplesCumulative,
                depthResearchAttach.performanceConsumerStaples
            )
        cumulativeInfo.consumerDiscretionaryCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.consumerDiscretionaryCumulative,
                depthResearchAttach.performanceConsumerDiscretionary
            )
        cumulativeInfo.informationTechnologyCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.informationTechnologyCumulative,
                depthResearchAttach.performanceInformationTechnology
            )
        cumulativeInfo.financialsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.financialsCumulative,
                depthResearchAttach.performanceFinancials
            )
        cumulativeInfo.healthCareCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.healthCareCumulative,
                depthResearchAttach.performanceHealthCare
            )
        cumulativeInfo.industrialsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.industrialsCumulative,
                depthResearchAttach.performanceIndustrials
            )
        cumulativeInfo.utilitiesCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.utilitiesCumulative,
                depthResearchAttach.performanceUtilities
            )
        cumulativeInfo.materialsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.materialsCumulative,
                depthResearchAttach.performanceMaterials
            )
        cumulativeInfo.realEstateCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.realEstateCumulative,
                depthResearchAttach.performanceRealEstate
            )
        cumulativeInfo.energyCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.energyCumulative,
                depthResearchAttach.performanceEnergy
            )
        cumulativeInfo.communicationServiceCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.communicationServiceCumulative,
                depthResearchAttach.performanceCommunicationSevices
            )
        cumulativeInfo.indexETFCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.indexETFCumulative,
                depthResearchAttach.performanceIndexETF
            )
        cumulativeInfo.cashCumulative =
            cumulativeCalc(lastDepthResearchAttach?.cumulativeInfo?.cashCumulative, depthResearchAttach.performanceCash)
        cumulativeInfo.othersCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.othersCumulative,
                depthResearchAttach.performanceOthers
            )
        cumulativeInfo.bigger10bnCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.bigger10bnCumulative,
                depthResearchAttach.performanceBigger10bn
            )
        cumulativeInfo.fiveTo10bnCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.fiveTo10bnCumulative,
                depthResearchAttach.performance5To10bn
            )
        cumulativeInfo.oneTo5bnCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.oneTo5bnCumulative,
                depthResearchAttach.performance1To5bn
            )
        cumulativeInfo.zeroPointThreeToOnebnCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.zeroPointThreeToOnebnCumulative,
                depthResearchAttach.performanceZeroPointThreeToOnebn
            )
        cumulativeInfo.litterZeroPointThreebnCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.litterZeroPointThreebnCumulative,
                depthResearchAttach.performanceLitterZeroPointThreebn
            )
        cumulativeInfo.equitiesCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.equitiesCumulative,
                depthResearchAttach.performanceEquities
            )
        cumulativeInfo.fixedIncomeCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.fixedIncomeCumulative,
                depthResearchAttach.performanceFixedIncome
            )
        cumulativeInfo.currenciesFXCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.currenciesFXCumulative,
                depthResearchAttach.performanceCurrenciesFX
            )
        cumulativeInfo.commoditiesCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.commoditiesCumulative,
                depthResearchAttach.performanceCommodities
            )
        cumulativeInfo.alternativeInvestmentsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.alternativeInvestmentsCumulative,
                depthResearchAttach.performanceAlternativeInvestments
            )
        cumulativeInfo.realEstateAssetClassCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.realEstateAssetClassCumulative,
                depthResearchAttach.performanceRealEstateAssetClass
            )
        cumulativeInfo.otherAssetClassCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.otherAssetClassCumulative,
                depthResearchAttach.performanceOthersAssetClass
            )
        cumulativeInfo.cashSpotCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.cashSpotCumulative,
                depthResearchAttach.performanceCashSpot
            )
        cumulativeInfo.futuresCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.futuresCumulative,
                depthResearchAttach.performanceFutures
            )
        cumulativeInfo.optionsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.optionsCumulative,
                depthResearchAttach.performanceOptions
            )
        cumulativeInfo.swapsCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.swapsCumulative,
                depthResearchAttach.performanceSwaps
            )
        cumulativeInfo.etfETPCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.etfETPCumulative,
                depthResearchAttach.performanceETFsETPs
            )
        cumulativeInfo.otherToolCumulative =
            cumulativeCalc(
                lastDepthResearchAttach?.cumulativeInfo?.otherToolCumulative,
                depthResearchAttach.performanceOthersTool
            )
        depthResearchAttach.cumulativeInfo = cumulativeInfo
    }


    /**
     * 计算基金季度数据
     */
    fun handleQuarterlyInfo(
        fund: Fund
    ) {
        val fundId = fund.fundId!!
        for (fundDepthResearchAttachInfoEntry in fundDepthResearchAttachDao.findAllByFundIdIs(fundId)
            .groupBy { it.dataMonth.year }) {
            val year = fundDepthResearchAttachInfoEntry.key
            for (fundQuarterDepthResearchAttachInfoEntry in fundDepthResearchAttachInfoEntry.value.groupBy { it.dataMonth.quarter() }) {
                val quarter = fundQuarterDepthResearchAttachInfoEntry.key
                val fundQuarterDepthResearchAttaches =
                    fundQuarterDepthResearchAttachInfoEntry.value.sortedBy { it.dataMonth }
                val fundDepthResearchAttachQuarterlyInfo =
                    fundDepthResearchAttachQuarterlyInfoDao.findByFundIdIsAndYearIsAndQuarterIs(
                        fundId,
                        year,
                        quarter
                    ) ?: FundDepthResearchAttachQuarterlyInfo(
                        fundId,
                        year,
                        quarter,
                    )
                fundDepthResearchAttachQuarterlyInfo.dataMonth = fundQuarterDepthResearchAttaches.last().dataMonth
                fundDepthResearchAttachQuarterlyInfo.longQuarterly =
                    fundQuarterDepthResearchAttaches.map { it.performanceLong ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchAttachQuarterlyInfo.shortQuarterly =
                    fundQuarterDepthResearchAttaches.map { it.performanceShort ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchAttachQuarterlyInfoDao.save(fundDepthResearchAttachQuarterlyInfo)
            }
        }
    }

    private fun cumulativeCalc(
        lastCumulative: BigDecimal?,
        cumulativeValue: BigDecimal?
    ): BigDecimal {
        val cumulativeBase = lastCumulative ?: BigDecimal.valueOf(100)
        val cumulativeResult =
            (cumulativeValue ?: BigDecimal.ZERO).divide(
                BigDecimal.valueOf(100),
                4,
                RoundingMode.HALF_UP
            ) + BigDecimal.ONE
        return (cumulativeBase * cumulativeResult).setScale(2, RoundingMode.HALF_UP)
    }

    /**
     * 计算指数年化数据
     */
    fun handleAnnuallyInfo(
        fund: Fund
    ) {
        val fundId = fund.fundId!!
        for (fundDepthResearchAttachAnnualInfoEntry in fundDepthResearchAttachDao.findAllByFundIdIs(fundId)
            .groupBy { it.dataMonth.year }) {
            val year = fundDepthResearchAttachAnnualInfoEntry.key
            val fundDepthResearchAttaches =
                fundDepthResearchAttachAnnualInfoEntry.value.sortedBy { it.dataMonth }
            val fundDepthResearchAttachAnnualInfo =
                fundDepthResearchAttachAnnualInfoDao.findByFundIdIsAndYearIs(
                    fundId,
                    year,
                ) ?: FundDepthResearchAttachAnnualInfo(
                    fundId,
                    year,
                )
            fundDepthResearchAttachAnnualInfo.dataMonth =
                fundDepthResearchAttaches.last().dataMonth
            fundDepthResearchAttachAnnualInfo.longAnnual =
                fundDepthResearchAttaches.map { it.performanceLong ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.shortAnnual =
                fundDepthResearchAttaches.map { it.performanceShort ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.uSAnnual =
                fundDepthResearchAttaches.map { it.performanceUS ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.canadaAnnual =
                fundDepthResearchAttaches.map { it.performanceCanada ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.brazilAnnual =
                fundDepthResearchAttaches.map { it.performanceBrazil ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.mexicoAnnual =
                fundDepthResearchAttaches.map { it.performanceMexico ?: BigDecimal.ZERO }.ytd(true)

            fundDepthResearchAttachAnnualInfo.argentinaAnnual =
                fundDepthResearchAttaches.map { it.performanceArgentina ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.chileAnnual =
                fundDepthResearchAttaches.map { it.performanceChile ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.colombiaAnnual =
                fundDepthResearchAttaches.map { it.performanceColombia ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.peruAnnual =
                fundDepthResearchAttaches.map { it.performancePeru ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.uKAnnual =
                fundDepthResearchAttaches.map { it.performanceUK ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.germanyAnnual =
                fundDepthResearchAttaches.map { it.performanceGermany ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.franceAnnual =
                fundDepthResearchAttaches.map { it.performanceFrance ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.switzerlandAnnual =
                fundDepthResearchAttaches.map { it.performanceSwitzerland ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.netherlandsAnnual =
                fundDepthResearchAttaches.map { it.performanceNetherlands ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.italyAnnual =
                fundDepthResearchAttaches.map { it.performanceItaly ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.spainAnnual =
                fundDepthResearchAttaches.map { it.performanceSpain ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.swedenAnnual =
                fundDepthResearchAttaches.map { it.performanceSweden ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.saudiArabiaAnnual =
                fundDepthResearchAttaches.map { it.performanceSaudiArabia ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.unitedArabEmiratesAnnual =
                fundDepthResearchAttaches.map { it.performanceUnitedArabEmirates ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.southAfricaAnnual =
                fundDepthResearchAttaches.map { it.performanceSouthAfrica ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.nigeriaAnnual =
                fundDepthResearchAttaches.map { it.performanceNigeria ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.egyptAnnual =
                fundDepthResearchAttaches.map { it.performanceEgypt ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.japanAnnual =
                fundDepthResearchAttaches.map { it.performanceJapan ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.chinaAnnual =
                fundDepthResearchAttaches.map { it.performanceChina ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.hongKongAnnual =
                fundDepthResearchAttaches.map { it.performanceHongKong ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.taiwanAnnual =
                fundDepthResearchAttaches.map { it.performanceTaiwan ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.australiaAnnual =
                fundDepthResearchAttaches.map { it.performanceAustralia ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.indiaAnnual =
                fundDepthResearchAttaches.map { it.performanceIndia ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.southKoreaAnnual =
                fundDepthResearchAttaches.map { it.performanceSouthKorea ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.singaporeAnnual =
                fundDepthResearchAttaches.map { it.performanceSingapore ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.indonesiaAnnual =
                fundDepthResearchAttaches.map { it.performanceIndonesia ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.malaysiaAnnual =
                fundDepthResearchAttaches.map { it.performanceMalaysia ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.thailandAnnual =
                fundDepthResearchAttaches.map { it.performanceThailand ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.philippinesAnnual =
                fundDepthResearchAttaches.map { it.performancePhilippines ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.vietnamAnnual =
                fundDepthResearchAttaches.map { it.performanceVietnam ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.newZealandAnnual =
                fundDepthResearchAttaches.map { it.performanceNewZealand ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.otherCountryAnnual =
                fundDepthResearchAttaches.map { it.performanceOtherCountry ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.consumerStaplesAnnual =
                fundDepthResearchAttaches.map { it.performanceConsumerStaples ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.consumerDiscretionaryAnnual =
                fundDepthResearchAttaches.map { it.performanceConsumerDiscretionary ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.informationTechnologyAnnual =
                fundDepthResearchAttaches.map { it.performanceInformationTechnology ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.financialsAnnual =
                fundDepthResearchAttaches.map { it.performanceFinancials ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.healthCareAnnual =
                fundDepthResearchAttaches.map { it.performanceHealthCare ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.industrialsAnnual =
                fundDepthResearchAttaches.map { it.performanceIndustrials ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.utilitiesAnnual =
                fundDepthResearchAttaches.map { it.performanceUtilities ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.materialsAnnual =
                fundDepthResearchAttaches.map { it.performanceMaterials ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.realEstateAnnual =
                fundDepthResearchAttaches.map { it.performanceRealEstate ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.energyAnnual =
                fundDepthResearchAttaches.map { it.performanceEnergy ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.communicationServiceAnnual =
                fundDepthResearchAttaches.map { it.performanceCommunicationSevices ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.indexETFAnnual =
                fundDepthResearchAttaches.map { it.performanceIndexETF ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.cashAnnual =
                fundDepthResearchAttaches.map { it.performanceCash ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.othersAnnual =
                fundDepthResearchAttaches.map { it.performanceOthers ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.bigger10bnAnnual =
                fundDepthResearchAttaches.map { it.performanceBigger10bn ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.fiveTo10bnAnnual =
                fundDepthResearchAttaches.map { it.performance5To10bn ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.oneTo5bnAnnual =
                fundDepthResearchAttaches.map { it.performance1To5bn ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.zeroPointThreeToOneAnnual =
                fundDepthResearchAttaches.map { it.performanceZeroPointThreeToOnebn ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.litterZeroPointThreebnAnnual =
                fundDepthResearchAttaches.map { it.performanceZeroPointThreeToOnebn ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.equitiesAnnual =
                fundDepthResearchAttaches.map { it.performanceEquities ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.fixedIncomeAnnual =
                fundDepthResearchAttaches.map { it.performanceFixedIncome ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.currenciesFXAnnual =
                fundDepthResearchAttaches.map { it.performanceCurrenciesFX ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.commoditiesAnnual =
                fundDepthResearchAttaches.map { it.performanceCommodities ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.realEstateAssetClassAnnual =
                fundDepthResearchAttaches.map { it.performanceRealEstateAssetClass ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.alternativeInvestmentsAnnual =
                fundDepthResearchAttaches.map { it.performanceAlternativeInvestments ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.otherAssetClassAnnual =
                fundDepthResearchAttaches.map { it.performanceOthersAssetClass ?: BigDecimal.ZERO }.ytd(true)

            fundDepthResearchAttachAnnualInfo.cashSpotAnnual =
                fundDepthResearchAttaches.map { it.performanceCashSpot ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.futuresAnnual =
                fundDepthResearchAttaches.map { it.performanceFutures ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.optionsAnnual =
                fundDepthResearchAttaches.map { it.performanceOptions ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.swapsAnnual =
                fundDepthResearchAttaches.map { it.performanceSwaps ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.etfETPAnnual =
                fundDepthResearchAttaches.map { it.performanceETFsETPs ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfo.otherToolAnnual =
                fundDepthResearchAttaches.map { it.performanceOthersTool ?: BigDecimal.ZERO }.ytd(true)
            fundDepthResearchAttachAnnualInfoDao.save(fundDepthResearchAttachAnnualInfo)
        }
    }


    /**
     * 计算对比的指数的信息
     */
    fun handleContrastAttach(
        fund: Fund
    ) {
        val fundId = fund.fundId!!
        val fundDepthResearchAttaches =
            fundDepthResearchAttachDao.findAllByFundIdIs(fund.fundId!!).sortedBy { it.dataMonth }
        val calcedDepthResearchAttaches = ArrayList<FundDepthResearchAttach>(fundDepthResearchAttaches.size + 1)
        fundDepthResearchAttaches.forEachIndexed { index, depthResearchAttach ->
            val currentMonth = depthResearchAttach.dataMonth
            calcedDepthResearchAttaches.add(depthResearchAttach)
            contrastDao.findAll().consumeAsyncBlocking { contrast ->
                val contrastId = contrast.id!!
                val calcedFundDepthResearchContrastAttaches =
                    ArrayList<FundDepthResearchContrastAttach>(fundDepthResearchAttaches.size + 1)

                val fundDepthResearchContrastAttach =
                    fundDepthResearchContrastAttachDao.findByFundIdEqualsAndContrastIdEqualsAndDataMonthEquals(
                        fundId,
                        contrastId,
                        currentMonth
                    ) ?: FundDepthResearchContrastAttach(fundId, contrastId, currentMonth)

                calcedFundDepthResearchContrastAttaches.add(fundDepthResearchContrastAttach)

                val contrastThreeMRollPerf =
                    findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(2), currentMonth)
                        .ytd() ?: BigDecimal.ZERO

                fundDepthResearchContrastAttach.threeMRollPerf =
                    if (index < 2) {
                        BigDecimal.ZERO
                    } else {
                        contrastThreeMRollPerf
                    }
                // 3M Roll Perf (Fund)- 3M Roll Perf (Benchmark)
                fundDepthResearchContrastAttach.threeMOutUnderPerf =
                    if (index < 2) {
                        BigDecimal.ZERO
                    } else {
                        depthResearchAttach.threeMRollPerf?.subtract(contrastThreeMRollPerf)
                    }


                val contrastSixMRollPerf =
                    findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(5), currentMonth)
                        .ytd() ?: BigDecimal.ZERO

                fundDepthResearchContrastAttach.sixMRollPerf =
                    if (index < 5) {
                        BigDecimal.ZERO
                    } else {
                        contrastSixMRollPerf
                    }

                // 6M Roll Perf (Fund)- 6M Roll Perf (Benchmark)
                fundDepthResearchContrastAttach.sixMOutUnderPerf =
                    if (index < 5) {
                        BigDecimal.ZERO
                    } else {
                        depthResearchAttach.sixMRollPerf?.subtract(contrastSixMRollPerf)
                    }

                val contrastLastTwelveMonthValues =
                    findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(11), currentMonth)

                val contrastTwelveMRollPerf =
                    contrastLastTwelveMonthValues
                        .ytd() ?: BigDecimal.ZERO

                fundDepthResearchContrastAttach.twelveMRollPerf =
                    if (index < 11) {
                        BigDecimal.ZERO
                    } else {
                        contrastTwelveMRollPerf
                    }

                // 12M Roll Perf (Fund)- 12M Roll Perf (Benchmark)
                fundDepthResearchContrastAttach.twelveMOutUnderPerf =
                    if (index < 11) {
                        BigDecimal.ZERO
                    } else {
                        depthResearchAttach.twelveMRollPerf?.subtract(contrastTwelveMRollPerf)
                    }

                val contrastThirtySixMRollPerf =
                    findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(35), currentMonth)
                        .ytd() ?: BigDecimal.ZERO

                fundDepthResearchContrastAttach.thirtySixMRollPerf =
                    if (index < 35) {
                        BigDecimal.ZERO
                    } else {
                        contrastThirtySixMRollPerf
                    }

                // 36M Roll Perf (Fund)- 36M Roll Perf (Benchmark)
                fundDepthResearchContrastAttach.thirtySixMOutUnderPerf =
                    if (index < 35) {
                        BigDecimal.ZERO
                    } else {
                        depthResearchAttach.thirtySixMRollPerf?.subtract(contrastThirtySixMRollPerf)
                    }

                fundDepthResearchContrastAttach.twelveMRollVol =
                    if (index < 11) {
                        BigDecimal.ZERO
                    } else {
                        findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(11), currentMonth)
                            .standardDeviation()
                    }
                fundDepthResearchContrastAttach.thirtySixMRollVol =
                    if (index < 35) {
                        BigDecimal.ZERO
                    } else {
                        findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(35), currentMonth)
                            .standardDeviation()
                    }
                // 两组数据求slope(线性回归率)：自变量（x）--- 过去12个月benchmark月回报，因变量（y）---过去12个月fund月回报
                val fundLastTwelveMonthValues =
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(11), currentMonth)
                fundDepthResearchContrastAttach.twelveMRollBeta =
                    if (index < 11) {
                        BigDecimal.ZERO
                    } else {
                        DataUtils.slope(
                            contrastLastTwelveMonthValues,
                            fundLastTwelveMonthValues
                        )
                    }
                // 两组数据求correlation coefficient(皮尔逊相关系数)： 过去12个月benchmark月回报；过去12个月fund月回报----python函数 numpy.corrcoef(x,y)
                fundDepthResearchContrastAttach.twelveMRollCorrel =
                    if (index < 11) {
                        BigDecimal.ZERO
                    } else {
                        DataUtils.pearsonCorrelation(
                            fundLastTwelveMonthValues,
                            contrastLastTwelveMonthValues,

                            )
                    }

                // 两组数据求slope(线性回归率)：自变量（x）--- 过去36个月benchmark月回报，因变量（y）---过去36个月fund月回报
                val contrastLastThirtySixMonthValues =
                    findContrastBusinessDataInTimeRange(contrastId, currentMonth.minusMonths(35), currentMonth)
                val fundLastThirtySixMonthValues =
                    findFundBusinessDataInTimeRange(fundId, currentMonth.minusMonths(35), currentMonth)
                fundDepthResearchContrastAttach.thirtySixMRollBeta =
                    if (index < 35) {
                        BigDecimal.ZERO
                    } else {
                        DataUtils.slope(
                            fundLastThirtySixMonthValues,
                            contrastLastThirtySixMonthValues,
                        )
                    }
                // 两组数据求correlation coefficient(皮尔逊相关系数)： 过去36个月benchmark月回报；过去36个月fund月回报----python函数 numpy.corrcoef(x,y)
                fundDepthResearchContrastAttach.thirtySixMRollCorrel =
                    if (index < 35) {
                        BigDecimal.ZERO
                    } else {
                        DataUtils.pearsonCorrelation(
                            fundLastThirtySixMonthValues,
                            contrastLastThirtySixMonthValues
                        )
                    }

                val contrastCurrentMonthValue =
                    contrastBusinessDataDao.findContrastBusinessDataByContrastIdAndTime(
                        contrastId,
                        currentMonth
                    )?.value?.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP) ?: BigDecimal.ZERO

                val fundCurrentMonthValue =
                    fundBusinessDataDao.findFundBusinessDataByFundIdAndTime(
                        fundId,
                        currentMonth
                    )?.value?.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP) ?: BigDecimal.ZERO

                // 当月Benchmark 回报 *上月及当月Exposure_Net的平均值
                fundDepthResearchContrastAttach.beta =
                    contrastCurrentMonthValue.multiply(
                        listOf(
                            (depthResearchAttach.exposureNet ?: BigDecimal.ZERO),
                            (if (index < 1) null else calcedDepthResearchAttaches[index - 1].exposureNet)
                        ).avg()
                    ).setScale(2, RoundingMode.HALF_UP)

                // 当月Benchmark 回报 *上月及当月Exposure_Long的平均值
                fundDepthResearchContrastAttach.betaLong =
                    contrastCurrentMonthValue.multiply(
                        listOf(
                            (depthResearchAttach.exposureLong ?: BigDecimal.ZERO),
                            (if (index < 1) null else calcedDepthResearchAttaches[index - 1].exposureLong)
                        ).avg()
                    ).setScale(2, RoundingMode.HALF_UP)

                // 当月Benchmark 回报 *上月及当月Exposure_Short的平均值
                fundDepthResearchContrastAttach.betaShort =
                    contrastCurrentMonthValue.multiply(
                        listOf(
                            (depthResearchAttach.exposureShort ?: BigDecimal.ZERO),
                            (if (index < 1) null else calcedDepthResearchAttaches[index - 1].exposureShort)
                        ).avg()
                    ).setScale(2, RoundingMode.HALF_UP)
                // 基金当月回报 - Beta
                fundDepthResearchContrastAttach.alpha = fundCurrentMonthValue
                    .multiply(BigDecimal.valueOf(100))
                    .subtract(fundDepthResearchContrastAttach.beta)
                // 基金当月回报 - Beta_Long
                fundDepthResearchContrastAttach.alphaLong = fundCurrentMonthValue
                    .multiply(BigDecimal.valueOf(100))
                    .subtract(fundDepthResearchContrastAttach.betaLong)
                // 基金当月回报 - Beta_Short
                fundDepthResearchContrastAttach.alphaShort = fundCurrentMonthValue
                    .multiply(BigDecimal.valueOf(100))
                    .subtract(fundDepthResearchContrastAttach.betaShort)
                // 类似基金return NAV，默认最早数据前一个月数值为100，之后每个月数据为前一个月值*（1+当月Beta Cumulative），举例：第一个月为100*（1+Beta [1]）；第二个月为 第一个月的值*（1+Beta [2]);
                val contrastLastAttach =
                    fundDepthResearchContrastAttachDao.findLastDataByFundId(fundId, contrastId, currentMonth)
                fundDepthResearchContrastAttach.betaCumulative =
                    cumulativeCalc(contrastLastAttach?.betaCumulative, fundDepthResearchContrastAttach.beta)
//                    (contrastLastAttach?.betaCumulative
//                        ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (contrastLastAttach?.beta
//                        ?: BigDecimal.ZERO)).setScale(
//                        2,
//                        RoundingMode.HALF_UP
//                    )

                // 算法同上，收益率改用Beta_Long
                fundDepthResearchContrastAttach.betaLongCumulative =
                    cumulativeCalc(contrastLastAttach?.betaLongCumulative, fundDepthResearchContrastAttach.betaLong)

//                    (contrastLastAttach?.betaLongCumulative
//                        ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (contrastLastAttach?.betaLong
//                        ?: BigDecimal.ZERO)).setScale(
//                        2,
//                        RoundingMode.HALF_UP
//                    )

                // 算法同上，收益率改用Beta_Short
                fundDepthResearchContrastAttach.betaShortCumulative =
                    cumulativeCalc(contrastLastAttach?.betaShortCumulative, fundDepthResearchContrastAttach.betaShort)

//                    (contrastLastAttach?.betaShortCumulative
//                        ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (contrastLastAttach?.betaShort
//                        ?: BigDecimal.ZERO)).setScale(
//                        2,
//                        RoundingMode.HALF_UP
//                    )

                // 算法同上，收益率改用Alpha
                fundDepthResearchContrastAttach.alphaCumulative =
                    cumulativeCalc(contrastLastAttach?.alphaCumulative, fundDepthResearchContrastAttach.alpha)

//                    (contrastLastAttach?.alphaCumulative
//                        ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (contrastLastAttach?.alpha
//                        ?: BigDecimal.ZERO)).setScale(
//                        2,
//                        RoundingMode.HALF_UP
//                    )

                // 算法同上，收益率改用Alpha_Long
                fundDepthResearchContrastAttach.alphaLongCumulative =
                    cumulativeCalc(contrastLastAttach?.alphaLongCumulative, fundDepthResearchContrastAttach.alphaLong)

//                    (contrastLastAttach?.alphaLongCumulative
//                        ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (contrastLastAttach?.alphaLong
//                        ?: BigDecimal.ZERO)).setScale(
//                        2,
//                        RoundingMode.HALF_UP
//                    )

                // 算法同上，收益率改用Alpha_Short
                fundDepthResearchContrastAttach.alphaShortCumulative =
                    cumulativeCalc(contrastLastAttach?.alphaShortCumulative, fundDepthResearchContrastAttach.alphaShort)

//                    (contrastLastAttach?.alphaShortCumulative
//                        ?: BigDecimal.valueOf(100)) * (BigDecimal.ONE + (contrastLastAttach?.alphaShort
//                        ?: BigDecimal.ZERO)).setScale(
//                        2,
//                        RoundingMode.HALF_UP
//                    )
                fundDepthResearchContrastAttachDao.save(fundDepthResearchContrastAttach)
            }
        }
        handleContrastQuarterlyInfo(fund)
        handleContrastAnnuallyInfo(fund)
    }

    /**
     * 计算指数季度数据
     */
    fun handleContrastQuarterlyInfo(
        fund: Fund
    ) {
        val fundId = fund.fundId!!
        for (fundDepthResearchContrastAttachInfoEntry in fundDepthResearchContrastAttachDao.findAllByFundId(fundId)
            .groupBy { "${it.fundId}-${it.contrastId}" }) {
            val contrastId = fundDepthResearchContrastAttachInfoEntry.key.split("-")[1].toInt()

            for (fundYearDepthResearchContrastAttachInfoEntry in fundDepthResearchContrastAttachInfoEntry.value.groupBy { it.dataMonth!!.year }) {
                val year = fundYearDepthResearchContrastAttachInfoEntry.key
                for (fundQuarterDepthResearchContrastAttachInfoEntry in fundYearDepthResearchContrastAttachInfoEntry.value.groupBy { it.dataMonth!!.quarter() }) {
                    val quarter = fundQuarterDepthResearchContrastAttachInfoEntry.key
                    val fundQuarterDepthResearchAttaches =
                        fundQuarterDepthResearchContrastAttachInfoEntry.value.sortedBy { it.dataMonth!! }
                    val fundDepthResearchContrastAttachQuarterlyInfo =
                        fundDepthResearchContrastAttachQuarterlyInfoDao.findByFundIdIsAndContrastIdIsAndYearIsAndQuarterIs(
                            fundId,
                            contrastId,
                            year,
                            quarter
                        ) ?: FundDepthResearchContrastAttachQuarterlyInfo(
                            fundId,
                            contrastId,
                            year,
                            quarter,
                        )
                    fundDepthResearchContrastAttachQuarterlyInfo.dataMonth =
                        fundQuarterDepthResearchAttaches.last().dataMonth!!
                    fundDepthResearchContrastAttachQuarterlyInfo.alphaQuarterly =
                        fundQuarterDepthResearchAttaches.map { it.alpha ?: BigDecimal.ZERO }.ytd(true)
                    fundDepthResearchContrastAttachQuarterlyInfo.betaQuarterly =
                        fundQuarterDepthResearchAttaches.map { it.beta ?: BigDecimal.ZERO }.ytd(true)
                    fundDepthResearchContrastAttachQuarterlyInfo.alphaLongQuarterly =
                        fundQuarterDepthResearchAttaches.map { it.alphaLong ?: BigDecimal.ZERO }.ytd(true)
                    fundDepthResearchContrastAttachQuarterlyInfo.alphaShortQuarterly =
                        fundQuarterDepthResearchAttaches.map { it.alphaShort ?: BigDecimal.ZERO }.ytd(true)
                    fundDepthResearchContrastAttachQuarterlyInfo.betaLongQuarterly =
                        fundQuarterDepthResearchAttaches.map { it.betaLong ?: BigDecimal.ZERO }.ytd(true)
                    fundDepthResearchContrastAttachQuarterlyInfo.betaShortQuarterly =
                        fundQuarterDepthResearchAttaches.map { it.betaShort ?: BigDecimal.ZERO }.ytd(true)
                    fundDepthResearchContrastAttachQuarterlyInfoDao.save(fundDepthResearchContrastAttachQuarterlyInfo)
                }
            }
        }
    }

    /**
     * 计算指数年化数据
     */
    fun handleContrastAnnuallyInfo(
        fund: Fund
    ) {
        val fundId = fund.fundId!!
        for (fundDepthResearchAttachAnnualInfoEntry in fundDepthResearchContrastAttachDao.findAllByFundId(fundId)
            .groupBy { "${it.fundId}-${it.contrastId}" }) {
            val contrastId = fundDepthResearchAttachAnnualInfoEntry.key.split("-")[1].toInt()

            for (fundYearDepthResearchAttachAnnualInfoEntry in fundDepthResearchAttachAnnualInfoEntry.value.groupBy { it.dataMonth!!.year }) {
                val year = fundYearDepthResearchAttachAnnualInfoEntry.key
                val fundDepthResearchContrastAttaches =
                    fundYearDepthResearchAttachAnnualInfoEntry.value.sortedBy { it.dataMonth }
                val fundDepthResearchContrastAttachAnnualInfo =
                    fundDepthResearchContrastAttachAnnualInfoDao.findByFundIdIsAndContrastIdIsAndYearIs(
                        fundId,
                        contrastId,
                        year,
                    ) ?: FundDepthResearchContrastAttachAnnualInfo(
                        fundId,
                        contrastId,
                        year,
                    )
                fundDepthResearchContrastAttachAnnualInfo.dataMonth =
                    fundDepthResearchContrastAttaches.last().dataMonth!!
                fundDepthResearchContrastAttachAnnualInfo.alphaAnnual =
                    fundDepthResearchContrastAttaches.map { it.alpha ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchContrastAttachAnnualInfo.betaAnnual =
                    fundDepthResearchContrastAttaches.map { it.beta ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchContrastAttachAnnualInfo.alphaLongAnnual =
                    fundDepthResearchContrastAttaches.map { it.alphaLong ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchContrastAttachAnnualInfo.alphaShortAnnual =
                    fundDepthResearchContrastAttaches.map { it.alphaShort ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchContrastAttachAnnualInfo.betaLongAnnual =
                    fundDepthResearchContrastAttaches.map { it.betaLong ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchContrastAttachAnnualInfo.betaShortAnnual =
                    fundDepthResearchContrastAttaches.map { it.betaShort ?: BigDecimal.ZERO }.ytd(true)
                fundDepthResearchContrastAttachAnnualInfoDao.save(fundDepthResearchContrastAttachAnnualInfo)
            }
        }
    }


    /**
     * 查询指定时间范围内的基金收益数据
     */
    private fun findFundBusinessDataInTimeRange(
        fundId: Int,
        startDate: LocalDate,
        endDate: LocalDate
    ): List<BigDecimal> {
        return jdbcTemplate.query(
            """
            select value from t_fund_bussiness_data
            where fund_id = ? and time between ? and ?
        """.trimIndent(), arrayOf<Any>(fundId, startDate, endDate), intArrayOf(Types.INTEGER, Types.DATE, Types.DATE)
        ) { rs, _ ->
            rs.getBigDecimal(1).divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP)
        }
    }

    /**
     * 查询指定时间范围内的指数收益数据
     */
    private fun findContrastBusinessDataInTimeRange(
        contrastId: Int,
        startDate: LocalDate,
        endDate: LocalDate
    ): List<BigDecimal> {
        return jdbcTemplate.query(
            """
            select value from t_contrast_bussiness_data
            where contrast_id = ? and time between ? and ?
        """.trimIndent(),
            arrayOf<Any>(contrastId, startDate, endDate),
            intArrayOf(Types.INTEGER, Types.DATE, Types.DATE)
        ) { rs, _ ->
            rs.getBigDecimal(1).divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP)
        }
    }

    fun findFundDepthResearchTimeRange(fundId: Int): Pair<LocalDate?, LocalDate?>? {
        val results = jdbcTemplate.query(
            """
            select min(data_month),
                   max(data_month)
            from t_fund_depth_research_attach where fund_id = ?
        """.trimIndent(), arrayOf<Any>(fundId), intArrayOf(Types.INTEGER)
        ) { rs, rowNum ->
            val startTime = rs.getDate(1)?.toLocalDate()
            val endTime = rs.getDate(2)?.toLocalDate()
            if (startTime == null && endTime == null) {
                return@query null
            }
            Pair(startTime, endTime)
        }.filterNotNull()
        return if (results.isEmpty()) {
            null
        } else {
            results.first()
        }
    }
}